import pygame
from pygame.locals import *
from sys import exit
from board import Board, BLANCO, NEGRO, VACIO
from others import *
from resources.sounds import Sounds 
from resources.fonts import Fonts 
from resources.images import Images 
from referee import Referee
import thread
from player import PC, HUMANO
from input_output.audio import Channel
from constants import RESOLUTION1, RESOLUTION2


class GraphicBoard:
    def __init__(self, dim=4, resolucion=RESOLUTION1):
        self.__tablero = Board(dim)
        #Inicializo el una matriz donde guardo las coordenadas de pantalla de cada celda
        self.__coordenadas = []
        for _ in xrange(self.__tablero.get_dimension()):
            self.__coordenadas.append([None]*self.__tablero.get_dimension())
        #Inicializo las variables x e y de las posiciones iniciales del tablero dependiendo de la resolucion
        self.__init_constants(resolucion)
        #Inicializo las imagenes del tablero
        self.__init_images(resolucion)
        #Inicializo las fuentes 
        self.__init_fonts()
        #Incializo variables que se utilizan en el algoritmo para la animacion de la celda seleccionada
        self.__nro_imagen = 0
        self.__factor = -1
        self.__cambiar_imagen = 0
        #Cargo en un vector las imagenes utilizadas en la animacion de la celda seleccionada
        efectos = Images.get_images_file_names(resolucion, "animacion_celda")
        self.__imagenes_celda_animada = [pygame.image.load(efectos["chica"]).convert(),pygame.image.load(efectos["mediana"]).convert(),pygame.image.load(efectos["grande"]).convert()] 
        self.__animated_cell = Coordinate()
        #Inicializo un reloj que utilizo para la animacion de la celda
        self.__reloj = pygame.time.Clock()
        self.lista_jugadas = []       
        #Inicializo constantes para identificar las esquinas del tablero
        self.__IARRIBA = 2
        self.__IABAJO = 3
        self.__DARRIBA = 4
        self.__DABAJO = 5
        #Inicializo contastes de direccion
        self.IZQ = -6
        self.DER = 6
        self.ARR = -7
        self.ABA = 7
        #Inicializo la superficie donde voy a guardar el tablero
        self.__init_surface()
        self.__do_animation_cell = True
        
    def __init_images(self,resolucion):
        na_imagenes_tablero = Images.get_images_file_names(resolucion, "tablero")
        na_imagenes_piezas = Images.get_images_file_names(resolucion, "piezas")
        #Cargo la imagen de la celda vacia
        self.__imagen_celda = pygame.image.load(na_imagenes_tablero["celda_vacia"]).convert()
        #Cargo la imagen de las cabeceras del tablero
        self.__imagen_tablero_bordev = pygame.image.load(na_imagenes_tablero["borde_vertical"]).convert()
        self.__imagen_tablero_bordeh = pygame.image.load(na_imagenes_tablero["borde_horizontal"]).convert()
        #Cargo las imagenes de las piezas
        self.__imagen_pieza_blanca = pygame.image.load(na_imagenes_piezas["blanca"]).convert_alpha()
        self.__imagen_pieza_negra = pygame.image.load(na_imagenes_piezas["negra"]).convert_alpha()
        self.__imagen_marca = pygame.image.load(na_imagenes_tablero["marca"]).convert_alpha()
    
    def __init_constants(self,resolucion):
        #Si la resolucion es de 800x600
        if resolucion == RESOLUTION1:
            self.__pos_ini = Coordinate(0,0)
            #Constantes que se utilizan en la funcion que renderea el tablero
            self.__inc_numero_borde_h = Coordinate(25,-5)
            self.__inc_numero_borde_vi = Coordinate(8,10)
            self.__inc_numero_borde_vd = Coordinate(7,10)
            self.__inc_borde_vd = Coordinate(70,0)
            self.__mitad_tam_celda = 35
            self.__tam_celda = 70
            self.__pos_graphic_board = Coordinate(219,0)
            self.__tam_fuente = 35
        #Si al resolucion es de 1200x900
        elif resolucion == RESOLUTION2:
            self.__pos_ini = Coordinate(0,0)
            #Constantes que se utilizan en la funcion que renderea el tablero
            self.__inc_numero_borde_h = Coordinate(35,-7)
            self.__inc_numero_borde_vi = Coordinate(10,17)
            self.__inc_numero_borde_vd = Coordinate(11,17)
            self.__inc_borde_vd = Coordinate(105,0)
            self.__mitad_tam_celda = 52
            self.__tam_celda = 105
            self.__pos_graphic_board = Coordinate(340,0)
            self.__tam_fuente = 50
        else:
            raise Exception("Resolucion desconocida (GraphicBoard Class)")            
    
    def __init_fonts(self):    
        self.__fuente = pygame.font.Font(Fonts.get_fonts_file_names()["fuente1"],self.__tam_fuente)
    
    def __init_surface(self):
        tam = (self.__mitad_tam_celda * 2) + (self.__tam_celda * self.__tablero.get_dimension())
        self.__surface = pygame.Surface((tam, tam), flags=SRCALPHA, depth=32)
    
    def get_board(self):
        return self.__tablero
    
    """
     
        Render a piece in a specific position on the board
        
        Params:
            - valor_casilla : BLACK or WHITE
            - x_s, y_s : surface render coordinate   
            - superficie : render surface      
    """
    def __render_piece(self,valor_casilla,x_s,y_s,superficie):
        if valor_casilla == BLANCO:
            superficie.blit(self.__imagen_pieza_blanca, (x_s,y_s))
        elif valor_casilla == NEGRO:
            superficie.blit(self.__imagen_pieza_negra, (x_s,y_s))
    
    """
    
        Render an empty cell in the screen
        
        Params:
            - celda_coord : cell screen coordinate
            - tablero_coord : cell board coordinate
            - ventana : render screen  
    """    
    def __render_cell(self,celda_coord, superficie):        
        #Coordenadas de pantalla
        x = celda_coord.x
        y = celda_coord.y        
        #Muestro la celda en blanco
        superficie.blit(self.__imagen_celda, (x,y))
    
    def render(self, ventana):
        self.__set_corner_pixels(ventana)
        self.__render_all_corners()
        self.__render_board()
        ventana.blit(self.__surface,(self.__pos_graphic_board.x,self.__pos_graphic_board.y))
    
    """
    
        Render the board in the graphic board surface
        
        Params:
            None
    """    
    def __render_board(self):        
        x = self.__pos_ini.x + self.__mitad_tam_celda
        for j in xrange(0, self.__tablero.get_dimension()):
            y = self.__pos_ini.y
            for i in xrange(0, self.__tablero.get_dimension()):            
                #Muestro el borde horizontal junto con el numero si es la primera fila
                if i == 0:                    
                    self.__surface.blit(self.__imagen_tablero_bordeh, (x,y))
                    #Numero del borde horizontal superior
                    nro_horizontal = self.__fuente.render(str(j+1), True, (255,255,0))                    
                    nx = x + self.__inc_numero_borde_h.x
                    ny = y + self.__inc_numero_borde_h.y
                    self.__surface.blit(nro_horizontal, (nx,ny))                  
                    y += self.__mitad_tam_celda
                #Calculo el numero a imprimir en el borde vertical
                nro_vertical = str(self.__tablero.get_dimension() - i)
                nro_vertical_text = self.__fuente.render(nro_vertical, True, (255,255,0))
                #Muestro el borde vertical izquierda junto con el numero si es la primera columna
                if j == 0:
                    self.__surface.blit(self.__imagen_tablero_bordev, (self.__pos_ini.x,y))
                    #Numero del borde vertical izquierda
                    nx = self.__pos_ini.x + self.__inc_numero_borde_vi.x
                    ny = y + self.__inc_numero_borde_vi.y
                    self.__surface.blit(nro_vertical_text, (nx,ny))
                #Render una celda vacio  
                self.__render_cell(Coordinate(x,y), self.__surface)                
                #Guardo la coordenada de pantalla de la celda
                self.__coordenadas[i][j] = Coordinate(x,y)
                #Muestro el borde vertical derecha junto con los numeros si es la ultima columna
                if j == self.__tablero.get_dimension() - 1:
                    nx = x + self.__inc_borde_vd.x
                    ny = y + self.__inc_borde_vd.y
                    self.__surface.blit(self.__imagen_tablero_bordev, (nx,ny)) 
                    #Numero del borde vertical izquierda
                    nx = nx + self.__inc_numero_borde_vd.x
                    ny = ny + self.__inc_numero_borde_vd.y   
                    self.__surface.blit(nro_vertical_text, (nx,ny))                         
                #Muestro el borde horizontal si es la ultima fila
                if i == self.__tablero.get_dimension() - 1:
                    y += self.__tam_celda
                    self.__surface.blit(self.__imagen_tablero_bordeh, (x,y))
                    #Numero del borde horizontal inferior
                    nx = x + self.__inc_numero_borde_h.x
                    ny = y + self.__inc_numero_borde_h.y
                    self.__surface.blit(nro_horizontal, (nx,ny))            
                y += self.__tam_celda
            x += self.__tam_celda            
    
    def render_configuration(self):
        self.__render_board()    
        dim = self.__tablero.get_dimension()
        superficie = self.__surface
        for i in xrange(0,dim):
            for j in xrange(0,dim):
                valor_casilla = self.__tablero.get_valor_casilla(i,j)
                if valor_casilla != VACIO:
                    x_s = self.__coordenadas[i][j].x
                    y_s = self.__coordenadas[i][j].y
                    self.__render_piece(valor_casilla, x_s, y_s, superficie)         
    
    def __render_background_corner(self,esquina):
        if esquina == self.__IARRIBA:
            x_ini = self.__pos_ini.x
            y_ini = self.__pos_ini.y
            esquina = self.__esquinaiarriba
        elif esquina == self.__IABAJO:
            x_ini = self.__pos_ini.x
            y_ini = self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())
            esquina = self.__esquinaiabajo  
        elif esquina == self.__DARRIBA:            
            x_ini = self.__pos_ini.x + self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())
            y_ini = self.__pos_ini.y
            esquina = self.__esquinadarriba
        elif esquina == self.__DABAJO:
            x_ini = self.__pos_ini.x + self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())
            y_ini = self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())
            esquina = self.__esquinadabajo
        for i in xrange(0,self.__mitad_tam_celda):
            x = x_ini + i
            for j in xrange(0,self.__mitad_tam_celda):
                y = y_ini + j
                self.__surface.set_at((x,y),esquina[i][j])
    
    def __render_all_corners(self):
        self.__render_background_corner(self.__IARRIBA)
        self.__render_background_corner(self.__IABAJO)
        self.__render_background_corner(self.__DARRIBA)
        self.__render_background_corner(self.__DABAJO)    
            
    def __get_corner_pixels(self,x_ini,y_ini,ventana):
        esquina = []
        for _ in xrange(self.__mitad_tam_celda):
            esquina.append([None]*self.__mitad_tam_celda)  
            
        for i in xrange(0,self.__mitad_tam_celda):
                for j in xrange(0,self.__mitad_tam_celda):
                    x = x_ini + i
                    y = y_ini + j
                    esquina[i][j] = ventana.get_at((x,y))
        return esquina
                            
    def __set_corner_pixels(self,ventana):            
        #Esquina Izquierda Arriba
        x_ini = self.__pos_graphic_board.x
        y_ini = self.__pos_graphic_board.y
        self.__esquinaiarriba = self.__get_corner_pixels(x_ini,y_ini,ventana)      
        #Esquina Izquierda Abajo  
        y_ini = self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())  
        self.__esquinaiabajo = self.__get_corner_pixels(x_ini, y_ini, ventana)
        #Esquina Derecha Arriba
        x_ini = self.__pos_graphic_board.x + self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())
        y_ini = self.__pos_graphic_board.y
        self.__esquinadarriba = self.__get_corner_pixels(x_ini, y_ini, ventana)
        #Esquina Derecha Abajo
        y_ini = self.__mitad_tam_celda + (self.__tam_celda * self.__tablero.get_dimension())
        self.__esquinadabajo = self.__get_corner_pixels(x_ini, y_ini, ventana)           
    
    """
        
        Render the animated cell
        
        Params:
            - pos_casilla : animated cell coordinate
            - ventana : render screen
    """
    def render_animation_cell(self, pos_casilla, ventana):
        #while self.__do_animation_cell:
        if not pos_casilla.equal(self.__animated_cell):               
            self.__animated_cell.set(pos_casilla)                
            self.__factor = -1
            self.__nro_imagen = 0              
        #Coordenadas de pantalla
        x = self.__coordenadas[pos_casilla.x][pos_casilla.y].x + self.__pos_graphic_board.x
        y = self.__coordenadas[pos_casilla.x][pos_casilla.y].y + self.__pos_graphic_board.y                                
        i = self.__nro_imagen
        f = self.__factor                      
        if i == 2 or i == 0:
            f *= -1 
        i = i + f
        ventana.blit(self.__surface,(self.__pos_graphic_board.x,self.__pos_graphic_board.y))                        
        ventana.blit(self.__imagenes_celda_animada[i], (x-(i+i),y-(i+i)))
        #Muestro alguna pieza si es que existe alguna en la celda animada
        valor_casilla = self.__tablero.get_valor_casilla(pos_casilla.x,pos_casilla.y)
        if valor_casilla != VACIO:
            self.__render_piece(valor_casilla,x,y,ventana)
        else:  
            #Si es una casilla vacia muestro alguna marca si es que existe alguna en la celda animada 
            self.__render_possible_move(pos_casilla, ventana)                         
        self.__nro_imagen = i
        self.__factor = f 
        pygame.time.wait(150)            
    
    """
    
        Get the new coordinate from the actual coordinate
        
        Params:
            - direccion : new coordinate direction (left,right,up,down)
            - coordenada_actual : actual coordinate
    """    
    def get_new_coordinates(self,direccion,coordenada_actual):
        coordenada_nueva = coordenada_actual
        
        if direccion == self.IZQ:
            if coordenada_actual.y > 0:
                coordenada_nueva.y -= 1
        elif direccion == self.DER:
            if coordenada_actual.y < self.__tablero.get_dimension() - 1:
                coordenada_nueva.y += 1
        elif direccion == self.ARR:
            if coordenada_actual.x > 0:
                coordenada_nueva.x -= 1
        elif direccion == self.ABA:
            if coordenada_actual.x < self.__tablero.get_dimension() - 1:
                coordenada_nueva.x += 1
        
        return coordenada_nueva    
    
    """
    
        Render a possible move if exist in the list of possibles moves 
        
        Params:
            - coord : possible move coordinate
            - ventana : render screen
    """
    def __render_possible_move(self,coord,ventana):
        coordenadas = self.__coordenadas
        for c in self.lista_jugadas:
            if c.x == coord.x and c.y == coord.y:
                x = coordenadas[c.x][c.y].x + self.__pos_graphic_board.x
                y = coordenadas[c.x][c.y].y + self.__pos_graphic_board.y   
                #Muestro la marca en el tablero
                ventana.blit(self.__imagen_marca, (x,y))
                break
    
    """
    
        Render a list of possibles moves
        
        Params:
            - ventana : render screen
    """
    def render_list_possible_moves(self, ventana):
        coordenadas = self.__coordenadas
        for c in self.lista_jugadas:
            x = coordenadas[c.x][c.y].x
            y = coordenadas[c.x][c.y].y    
            #Muestro la marca en el tablero
            self.__surface.blit(self.__imagen_marca, (x,y))
    
    def __render_animation_image(self,imagen,inc,coord,ventana):
        x = self.__coordenadas[coord.x][coord.y].x + self.__pos_graphic_board.x
        y = self.__coordenadas[coord.x][coord.y].y + self.__pos_graphic_board.y
        ventana.blit(imagen, (x-inc,y-inc))
        self.__render_piece(self.__tablero.get_valor_casilla(coord.x,coord.y),x,y,ventana)
            
    def __render_line_animation(self,linea,color,sonido,canal,ventana):
        canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["linea_entre"])
        sonido_coord = self.__get_sound(linea["casilla_inicial"]) 
        canal.queue(sonido_coord['columna'])
        canal.queue(sonido_coord['fila'])
        canal.queue(Sounds.get_sounds_file_names("otros")["y"])
        sonido_coord = self.__get_sound(linea["casilla_final"]) 
        canal.queue(sonido_coord['columna'])
        canal.queue(sonido_coord['fila'])
        canal.send_new_sound_event()
        i = self.__nro_imagen
        f = self.__factor
        can_casillas_v = linea["can_fichas_volteables"] - 1    
        while can_casillas_v >= 0:                          
            if canal.silence():
                self.__tablero.turn_pieces2(linea["casillas_volteables"][can_casillas_v],color)
                can_casillas_v = can_casillas_v - 1
                canal.queue(sonido)
                canal.send_new_sound_event()
                self.render_configuration()
            if i == 2:
                f *= -1
            elif i == 0:
                f *= -1
            i = i + f
            ventana.blit(self.__surface,(self.__pos_graphic_board.x,self.__pos_graphic_board.y))
            self.__render_animation_image(self.__imagenes_celda_animada[i], i+i, linea["casilla_inicial"], ventana)
            for casilla in linea["casillas_volteables"]:    
                self.__render_animation_image(self.__imagenes_celda_animada[i], i+i, casilla, ventana)             
            self.__render_animation_image(self.__imagenes_celda_animada[i], i+i, linea["casilla_final"], ventana)
            pygame.display.update()
            pygame.time.wait(200)
    
    def __get_sound(self,coord):
        sonido_coordenada = {}
        dim = self.__tablero.get_dimension()
        sonido_coordenada['fila'] = Sounds.get_sounds_file_names("tablero")["numeros"][str(dim-coord.x)]
        sonido_coordenada['columna'] = Sounds.get_sounds_file_names("tablero")["numeros"][str(coord.y+1)]
        return sonido_coordenada
    
    def __play_move_sound(self, canal, coord):        
        sonido_coordenada = self.__get_sound(coord)
        canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["jugada_en"]) 
        canal.queue(sonido_coordenada['columna'])
        canal.queue(sonido_coordenada['fila'])
        canal.send_new_sound_event() 
    
    def set_piece(self, coord, color, sonido, canal, ventana):
        pudo_colocar = self.__tablero.set_piece(coord,color)
        if pudo_colocar:
            canal.stop()
            canal.queue(sonido)
            canal.send_new_sound_event()
            self.render_configuration() 
            self.__play_move_sound(canal,coord)                        
            return True 
        else:
            return False
    
    def do_line_animation(self, coord, color, sonido, canal, marcador, ventana):
        lineas_formadas = self.get_board().get_lines(color,coord)
        for linea in lineas_formadas:            
            self.__render_line_animation(linea,color,sonido,canal,ventana)
            marcador.show(self.get_board(),ventana,color)
    
        
    def play_box_sound(self, canal, coord, lista_jugadas):
        tablero = self.__tablero
        jugada_posible = False
        for jugada in lista_jugadas:
            if jugada.x == coord.x and jugada.y == coord.y:
                canal.queue(Sounds.get_sounds_file_names("tablero")["fx"]["jugada_posible"])
                canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["jugada_posible"])                
                canal.send_new_sound_event()
                jugada_posible = True
                break
        if not jugada_posible:        
            valor_casilla = tablero.get_valor_casilla(coord.x,coord.y)
            if valor_casilla == VACIO:              
                canal.queue(Sounds.get_sounds_file_names("tablero")["fx"]["vacio"])
                canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["vacio"])
                canal.send_new_sound_event() 
            elif valor_casilla == BLANCO:      
                canal.queue(Sounds.get_sounds_file_names("tablero")["fx"]["blanca"])
                canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["blanca"])
                canal.send_new_sound_event()
            elif valor_casilla == NEGRO:
                canal.queue(Sounds.get_sounds_file_names("tablero")["fx"]["negra"])
                canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["negra"])
                canal.send_new_sound_event()       

class Score:
    def __init__(self, resolucion=(800,600)):
        #Inicilializo las constasntes graficas dependiendo de la resolucion
        self.__init_constants(resolucion)
        #Inicializo las fuentes
        self.__init_fonts()
        #Inicializo las imagenes
        self.__init_images(resolucion)
    
    def __init_constants(self,resolucion):
        #Si la resolucion es de 800x600
        if resolucion == RESOLUTION1:
            self.__barra_iz = Coordinate(0,0)
            self.__barra_de = Coordinate(700,0)
            self.__bandera_blanca = Coordinate(6,6)
            self.__bandera_negra = Coordinate(706,6)
            self.__tam_fuente = 60
            #TODO: Cambiar los valores de abajo para 800x600
            self.__x_marcador_iz = 25
            self.__x_marcador_de = 1075
            self.__y_marcador = 350
        #Si la resolucion es de 1200x900
        elif resolucion == RESOLUTION2:
            self.__barra_iz = Coordinate(0,0)
            self.__barra_de = Coordinate(1050,0)
            self.__bandera_blanca = Coordinate(9,7)
            self.__bandera_negra = Coordinate(1059,7)
            self.__tam_fuente = 80
            self.__x_marcador_iz = 25
            self.__x_marcador_de = 1075
            self.__y_marcador = 350
        else:
            raise Exception("Resolucion desconocida (Score Class)")            
        #Iniciliazo los colores de las fuentes
        self.__color_negro = (0,0,0)
        self.__color_amarillo = (255,255,0)
    
    def __init_fonts(self):
        self.__fuente = pygame.font.Font(Fonts.get_fonts_file_names()["fuente1"],self.__tam_fuente)
    
    def __init_images(self, resolucion):
        na_imagenes_marcador = Images.get_images_file_names(resolucion, "marcador")
        self.__imagen_barra_negra = pygame.image.load(na_imagenes_marcador["barra_negra"]).convert_alpha()
        self.__imagen_barra_amarilla = pygame.image.load(na_imagenes_marcador["barra_amarilla"]).convert_alpha()
        self.__imagen_bandera_negra = pygame.image.load(na_imagenes_marcador["bandera_negra"]).convert_alpha()
        self.__imagen_bandera_blanca = pygame.image.load(na_imagenes_marcador["bandera_blanca"]).convert_alpha()
    
    def show(self,tablero,ventana,turno):
        #Copio la barra izquierda del marcador cambiando el color dependiendo del turno
        if turno == BLANCO:            
            ventana.blit(self.__imagen_barra_amarilla, (self.__barra_iz.x,self.__barra_iz.y))
            color_fuente_barra_iz = self.__color_negro
        else:
            ventana.blit(self.__imagen_barra_negra, (self.__barra_iz.x,self.__barra_iz.y))
            color_fuente_barra_iz = self.__color_amarillo
        #Copio la bandera blanca sobre la barra
        ventana.blit(self.__imagen_bandera_blanca, (self.__bandera_blanca.x,self.__bandera_blanca.y))
        #Copio la barra derecha del marcador
        if turno == NEGRO:
            ventana.blit(self.__imagen_barra_amarilla, (self.__barra_de.x,self.__barra_de.y))
            color_fuente_barra_de = self.__color_negro
        else:
            ventana.blit(self.__imagen_barra_negra, (self.__barra_de.x,self.__barra_de.y))
            color_fuente_barra_de = self.__color_amarillo
        #Copio la bandera negra sobre la barra
        ventana.blit(self.__imagen_bandera_negra, (self.__bandera_negra.x,self.__bandera_negra.y))    
        marcador_blancas = tablero.get_number_white_pieces()
        marcador_negras = tablero.get_number_black_pieces()
        if marcador_blancas < 10:
            marcador_blancas = "0" + str(marcador_blancas)
        else:
            marcador_blancas = str(marcador_blancas)
        if marcador_negras < 10:
            marcador_negras = "0" + str(marcador_negras)
        else:
            marcador_negras = str(marcador_negras)
        #Muestro los marcadores 
        ventana.blit(self.__fuente.render(marcador_blancas, True, color_fuente_barra_iz), (self.__x_marcador_iz,self.__y_marcador))
        ventana.blit(self.__fuente.render(marcador_negras, True, color_fuente_barra_de), (self.__x_marcador_de,self.__y_marcador))
        
class TextBox:
    def __init__(self, resolucion=(800,600)):
        na_otras_imagenes = Images.get_images_file_names(resolucion, "etc")
        self.__image = pygame.image.load(na_otras_imagenes["caja_texto"]).convert_alpha()
        self.__init_constants(resolucion)
        self.__init_fonts()
        #Inicializo un reloj que utilizo para la animacion del textbox
        self.__reloj_t = pygame.time.Clock()
        
    def __init_constants(self,resolucion):
        #Si la resolucion es de 800x600
        if resolucion == RESOLUTION1:
            self.__tam_fuente = 30
            self.__y_max = 350
            self.__y_inicial = 600.
            self.__velocidad = 350.
        elif resolucion == RESOLUTION2:
            self.__tam_fuente = 30
            self.__y_max = 525
            self.__y_inicial = 900.
            self.__velocidad = 400.
        else:
            raise Exception("Resolucion desconocida (Text Box Class)")            
    
    def __init_fonts(self):
        self.__fuente = pygame.font.Font(Fonts.get_fonts_file_names()["fuente1"] ,self.__tam_fuente)
    
    def write(self,texto):
        self.__contenido = self.__fuente.render(str(texto), True, (0,0,0))
        
    def show(self,superficie):        
        y = self.__y_inicial
        velocidad = self.__velocidad   
        reloj = pygame.time.Clock()     
        while y >= self.__y_max:
            superficie.blit(self.__image, (0, y))            
            tiempo_pasado = reloj.tick()
            tiempo_pasado_segundos = tiempo_pasado / 1000.0            
            distancia = tiempo_pasado_segundos * velocidad
            y -= distancia       
            pygame.display.update()        
        superficie.blit(self.__contenido, (350,600))

class Gui:
    def __init__(self, titulo_ventana="Club de Othello"):
        try:         
            #Iniciliazo el canal para reproducir los sonidos
            self.__canal = Channel()          
            pygame.init()  
            #Averiguo la resolucion necesario para crear la ventana
            self.__resolucion = self.__get_initial_resolution()
            #Creo la ventana
            self.ventana = pygame.display.set_mode(self.__resolucion, 0, 32)
            #Coloco el titulo a la ventana
            pygame.display.set_caption(titulo_ventana)      
            pygame.mouse.set_visible(False)      
        except pygame.error:
            raise Exception("ERROR!, no se pudieron inicializar los elementos graficos")            

    def __get_initial_resolution(self):
        maxima_resolucion = pygame.display.list_modes()[0]
        if maxima_resolucion[0] >= 1200 and maxima_resolucion[1] >= 900:
            return (1200,900)
        else:
            return (800,600)
    
    def get_resolution(self):
        return self.__resolucion            
    
    def __render_character(self):
        na_imagenes_personajes = Images.get_images_file_names(self.__resolucion, "personajes")
        if self.__resolucion == RESOLUTION1:
            self.ventana.blit(pygame.image.load(na_imagenes_personajes["pablo_gris"]).convert_alpha(), (110,150))
        else:
            self.ventana.blit(pygame.image.load(na_imagenes_personajes["pablo_gris"]).convert_alpha(), (100,50))
    
    def __play_move_sound(self,direccion):
        if direccion == self.__tablero_grafico.DER:
            self.__canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["derecha"])
            self.__canal.send_new_sound_event()
        elif direccion == self.__tablero_grafico.IZQ:
            self.__canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["izquierda"])
            self.__canal.send_new_sound_event()
        elif direccion == self.__tablero_grafico.ABA:
            self.__canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["abajo"])
            self.__canal.send_new_sound_event()
        elif direccion == self.__tablero_grafico.ARR:
            self.__canal.queue(Sounds.get_sounds_file_names("tablero")["voz"]["arriba"])
            self.__canal.send_new_sound_event()
    
    def init_board(self,dim=4):
        self.__tablero_grafico = GraphicBoard(dim,self.get_resolution())
        return self.__tablero_grafico
    
    def get_graphic_board(self):
        return self.__tablero_grafico
    
    def run(self,juego):
        tablero_g = self.__tablero_grafico
        marcador = Score(self.get_resolution())
        caja_texto = TextBox(self.get_resolution())
        coord = Coordinate(0,0)             
        #Copio la imagen de fondo
        self.ventana.blit(pygame.image.load(Images.get_images_file_names(self.get_resolution(), "habitaciones")["aula"]).convert(), (0,0))
        #Copio la imagen del personaje
        self.__render_character()          
        #Muestro el tablero con su configuracion
        tablero_g.render(self.ventana)
        tablero_g.render_configuration()
        #Busco si es que hay jugadas posibles para la configuracion inicial
        if Referee.is_at_least_one_move(juego.get_turn().get_color(), tablero_g.get_board()):                
            tablero_g.lista_jugadas = Referee.possibles_moves(juego.get_turn().get_color(),tablero_g.get_board())
            tablero_g.render_list_possible_moves(self.ventana)
        #Muestro los marcadores iniciales
        marcador.show(tablero_g.get_board(),self.ventana,juego.get_turn().get_color())
        #Iniciliazo un canal para sonidos
        canal = self.__canal
        thread.start_new_thread(canal.listen,())
        #Iniciliazo los sonidos
        sonido_blanca = Sounds.get_sounds_file_names("tablero")["fx"]["blanca"]
        sonido_negra = Sounds.get_sounds_file_names("tablero")["fx"]["negra"]
        sonido_voltear_blanca = Sounds.get_sounds_file_names("tablero")["fx"]["voltear_blanca"]
        sonido_voltear_negra = Sounds.get_sounds_file_names("tablero")["fx"]["voltear_negra"]
        while True:                    
            for event in pygame.event.get():
                if event.type == KEYDOWN: 
                    #Ejecuto el sonido
                    canal.stop()
                    canal.queue(Sounds.get_sounds_file_names("tablero")["fx"]["mover_seleccion"])
                    canal.send_new_sound_event()
                    if event.key == K_KP4:
                        self.__play_move_sound(tablero_g.IZQ)
                        coord = tablero_g.get_new_coordinates(tablero_g.IZQ, coord)                       
                        tablero_g.play_box_sound(canal,coord,tablero_g.lista_jugadas)
                    elif event.key == K_KP6:
                        self.__play_move_sound(tablero_g.DER)
                        coord = tablero_g.get_new_coordinates(tablero_g.DER, coord)
                        tablero_g.play_box_sound(canal,coord,tablero_g.lista_jugadas)
                    elif event.key == K_KP8:
                        self.__play_move_sound(tablero_g.ARR)
                        coord = tablero_g.get_new_coordinates(tablero_g.ARR, coord)
                        tablero_g.play_box_sound(canal,coord,tablero_g.lista_jugadas)
                    elif event.key == K_KP2:
                        self.__play_move_sound(tablero_g.ABA)
                        coord = tablero_g.get_new_coordinates(tablero_g.ABA, coord)
                        tablero_g.play_box_sound(canal,coord,tablero_g.lista_jugadas)
                    elif event.key == K_KP9:
                        nombre_de_turno = juego.get_turn().get_name()
                        color_de_turno =  juego.get_turn().get_color()
                        if nombre_de_turno == HUMANO:
                            if color_de_turno == BLANCO:                                
                                pudo_jugar = tablero_g.set_piece(coord,color_de_turno,sonido_blanca,canal,self.ventana)                                
                                sonido_voltear = sonido_voltear_negra 
                            else:
                                pudo_jugar = tablero_g.set_piece(coord,color_de_turno,sonido_negra,canal,self.ventana)  
                                sonido_voltear = sonido_voltear_blanca                  
                            if pudo_jugar:
                                marcador.show(tablero_g.get_board(),self.ventana,juego.get_turn().get_color())
                                pygame.event.post(pygame.event.Event(self.__canal.SILENCE_CHANNEL))                                
                        elif nombre_de_turno == PC:
                            pudo_jugar = juego.play_pc()                            
                            if pudo_jugar:
                                coord.set(juego.get_last_pc_move())
                                if color_de_turno == BLANCO:
                                    pudo_jugar = tablero_g.set_piece(coord,color_de_turno,sonido_blanca,canal,self.ventana)
                                    sonido_voltear = sonido_voltear_negra
                                else:
                                    pudo_jugar = tablero_g.set_piece(coord,color_de_turno,sonido_negra,canal,self.ventana)
                                    sonido_voltear = sonido_voltear_blanca 
                                marcador.show(tablero_g.get_board(),self.ventana,juego.get_turn().get_color())
                                pygame.event.post(pygame.event.Event(self.__canal.SILENCE_CHANNEL))                            
                        else:
                            print "Error!, el turno no pertenece ni al Humano ni a la PC"
                            exit()                                                                                                                                                                    
                    elif event.key == K_ESCAPE:     
                        canal.end()              
                        exit()
                elif event.type == self.__canal.SILENCE_CHANNEL:
                    if canal.silence():
                        tablero_g.do_line_animation(coord, color_de_turno, sonido_voltear, canal, marcador, self.ventana)
                        juego.change_turn() 
                        tablero_g.lista_jugadas = Referee.possibles_moves(juego.get_turn().get_color(),tablero_g.get_board())
                        tablero_g.render_list_possible_moves(self.ventana)     
                        marcador.show(tablero_g.get_board(),self.ventana,juego.get_turn().get_color())                                                    
                        if juego.is_over():                                
                            caja_texto.write(juego.get_final_result())
                            caja_texto.show(self.ventana)
                    else:
                        pygame.event.post(pygame.event.Event(self.__canal.SILENCE_CHANNEL))            
            tablero_g.render_animation_cell(coord,self.ventana)                       
            #Refresco la pantalla       
            pygame.display.update()        